package com.grm.workflow.service.impl;

import com.grm.common.entity.PageResult;
import com.grm.workflow.request.deploy.WfDeployQueryParam;
import com.grm.workflow.response.WfDeployResponse;
import com.grm.workflow.service.WfDeployService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.flowable.common.engine.impl.db.SuspensionState;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.repository.ProcessDefinitionQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
@Slf4j
public class WfDeployServiceImpl implements WfDeployService {
    @Autowired
    private RepositoryService repositoryService;

    @Override
    public PageResult<WfDeployResponse> querySelective(Integer pageNum, Integer pageSize, WfDeployQueryParam queryParam) {
        // 流程定义列表数据查询
        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery()
                .latestVersion()
                .orderByProcessDefinitionKey()
                .asc();
        // 流程标识
        if (StringUtils.isNotBlank(queryParam.getProcessKey())) {
            processDefinitionQuery.processDefinitionKeyLike("%" + queryParam.getProcessKey() + "%");
        }
        // 流程名称
        if (StringUtils.isNotBlank(queryParam.getProcessName())) {
            processDefinitionQuery.processDefinitionNameLike("%" + queryParam.getProcessName() + "%");
        }
        // 流程分类
        if (StringUtils.isNotBlank(queryParam.getCategory())) {
            processDefinitionQuery.processDefinitionCategory(queryParam.getCategory());
        }
        // 流程状态
        if (StringUtils.isNotBlank(queryParam.getState())) {
            if (SuspensionState.ACTIVE.toString().equals(queryParam.getState())) {
                processDefinitionQuery.active();
            } else if (SuspensionState.SUSPENDED.toString().equals(queryParam.getState())) {
                processDefinitionQuery.suspended();
            }
        }
        /*
        SELECT COUNT(*) FROM act_re_procdef WHERE ...
         */
        long pageTotal = processDefinitionQuery.count();
        if (pageTotal <= 0) {
            return new PageResult<>(List.of(), 0L);
        }
        /*
        SELECT * FROM act_re_procdef WHERE ...
         */
        List<ProcessDefinition> definitionList = processDefinitionQuery.listPage((pageNum - 1) * pageSize, pageSize);
        List<WfDeployResponse> deployResponseList = new ArrayList<>(definitionList.size());
        for (ProcessDefinition processDefinition : definitionList) {
            String deploymentId = processDefinition.getDeploymentId();
            /*
            SELECT * FROM act_re_deployment WHERE id_ = ?

            SELECT pd.*, d.*
            FROM act_re_procdef pd
            JOIN act_re_deployment d ON pd.deployment_id_ = d.id_
            WHERE pd.id_ = ?
             */
            Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId).singleResult();
            WfDeployResponse wfDeployResponse = getWfDeployResponse(processDefinition, deployment);
            deployResponseList.add(wfDeployResponse);
        }
        return new PageResult<>(deployResponseList, pageTotal);
    }

    private WfDeployResponse getWfDeployResponse(ProcessDefinition processDefinition, Deployment deployment) {
        WfDeployResponse wfDeployResponse = new WfDeployResponse();
        wfDeployResponse.setDefinitionId(processDefinition.getId());
        wfDeployResponse.setProcessKey(processDefinition.getKey());
        wfDeployResponse.setProcessName(processDefinition.getName());
        wfDeployResponse.setVersion(processDefinition.getVersion());
        wfDeployResponse.setCategory(processDefinition.getCategory());
        wfDeployResponse.setDeploymentId(processDefinition.getDeploymentId());
        wfDeployResponse.setSuspended(processDefinition.isSuspended());
        wfDeployResponse.setDeploymentTime(deployment.getDeploymentTime());
        return wfDeployResponse;
    }
}
